package com.offcn.itcast;

import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.*;

/*
单例设计模式的实现
1、一个类值能有一个实例（构造器私有化）
2、能够自行创建这个实例（含有一个该类的静态变量用于保存这个唯一的实例）
3、必须自行向整个系统提供这个实例（对外提供获取该实例对象的方式）
（1）、直接暴露
（2）、用静态变量的get方法获取该实例
 */
/*
常见实现的几种方式：
饿汉式、直接创建对象，不存在线程安全问题
    （1）直接实例化饿汉式（简洁直观）
    （2）、枚举方式（最简洁）
    （3）、静态代码块实现饿汉式（适合复杂实例化）
懒汉式：延迟创建对象
    （1）、线程不安全（适用于单线程）
    （2）、线程安全（适合于多线程）
    （3）、静态内部形式（适合于多线程）
 */
public class Test01 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
       /* Singleton03 instance = Singleton03.INSTANCE;
        Singleton03 instance2 = Singleton03.INSTANCE;
        System.out.println(instance == instance2);//判断两个引用是否执行同一地址
        System.out.println(instance);*/
       Callable<Singleton04> c = new Callable<Singleton04>() {

           @Override
           public Singleton04 call() throws Exception {
               return Singleton04.getInstance();
           }
       };

       //使用线程池创建线程
        ExecutorService es = Executors.newFixedThreadPool(3);
        Future<Singleton04> f1 = es.submit(c);
        Future<Singleton04> f2 = es.submit(c);
        Future<Singleton04> f3 = es.submit(c);

        Singleton04 s1 = f1.get();
        Singleton04 s2 = f2.get();
        Singleton04 s3 = f3.get();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);

        es.shutdown();

    }
}
/*
不管是否需要都会常见对象
饿汉式，直接实例化对象
 */
class Singleton01 {

   public static final Singleton01 INSTANCE = new Singleton01();
    private Singleton01() {}

}
/*
枚举 指的对象是有限几个类
饿汉式，枚举形式实现
 */
 enum  Singleton02 {

    INSTANCE,

}
/*
静态代码块实现单例模式
 */
class Singleton03 {
    public static final  Singleton03 INSTANCE;
    private String info;

    static {
        try {
            Properties pro = new Properties();
            pro.load(Singleton03.class.getClassLoader().getResourceAsStream("config.properties"));
            INSTANCE = new Singleton03(pro.getProperty("info"));
        } catch (IOException e) {
           throw new RuntimeException(e);
        }

    }

    private Singleton03(String info) {
        this.info = info;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Singleton03{" +
                "info='" + info + '\'' +
                '}';
    }
}
/*
懒汉模式
线程不安全
 */
class Singleton04 {
    private Singleton04() { }

    private static Singleton04 instance;

    public static Singleton04 getInstance() {

        if(instance == null)  {
            instance = new Singleton04();
        }
        return instance;
    }
}
/*
线程安全模式
 */
class Singleton05 {

    private static Singleton05 instance;

    private Singleton05() {
    }

   public static Singleton05 getInstance() {
        synchronized (Singleton05.class) {
            if(instance == null) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                instance = new Singleton05();
            }
        }
        return instance;
   }

}
/*
DCl double check lock
 */
class Singleton06 {
    private static volatile Singleton06 instance;

    private Singleton06() {

    }

    public static  Singleton06 getInstance() {
        //提升效率
        if(instance == null) {
            synchronized(Singleton06.class) {
                //保证单例
                if(instance == null) {
                    instance = new Singleton06();
                }
            }
        }
        return instance;
    }

}
/*
使用内部类创建单例
使用静态内部类实现单例模式
在内部类被加载和初始化时，才会创建INSTANCE实例对象
静态内部类不会自动随着外部类的加载和初始化而初始化，静态内部类需要单独加载和初始化
 */
class Singleton07 {
    private Singleton07() { }

    private  static class Inner {
        private static final Singleton07 INSTANCE= new Singleton07();
    }

    public static Singleton07 getInstance() {
        return Inner.INSTANCE;
    }
}























